﻿Imports System.Net.Sockets
Imports System.Text
Imports System.Net
Imports System.Threading.Tasks
Imports System.Threading

Public Class Connections
    Public Client As TcpClient
    Public Stream As NetworkStream
    Public Sock As Socket
    Private _bb As New List(Of Byte)
    Private _DataQueue As Queue(Of Byte)
    Private _LastReadLength As Integer
    Private _Buffer(1024) As Byte
    Public Event dataResponse(ByVal response() As String)
    Public Event onDisconnected()

    Public Function isConnected() As Boolean
        If Sock.Connected Then
            If Sock.Poll(0, SelectMode.SelectRead) = False Or (Sock.Poll(0, SelectMode.SelectWrite) = True And Sock.Poll(0, SelectMode.SelectError) = False) Then
                Dim buffer() As Byte = New Byte(1) {}
                Sock.ReceiveTimeout = False
                Try
                    If Sock.Receive(buffer, SocketFlags.Peek) = 0 Then
                        Return False
                    Else
                        Return True
                    End If
                Catch ex As SocketException
                    Return True
                End Try
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function

    Public Sub New(address As IPAddress, port As Integer)
        Client = New TcpClient
        Client.Connect(address, port)
        Sock = Client.Client
        Stream = Client.GetStream
        _DataQueue = New Queue(Of Byte)
    End Sub

    Public Sub New(host As String, port As Integer)
        Client = New TcpClient
        Client.Connect(host, port)
        Sock = Client.Client
        Stream = Client.GetStream
        _DataQueue = New Queue(Of Byte)
    End Sub

    Public Sub AwaitData()
        _Buffer = New Byte(1024) {}
        Stream.BeginRead(_Buffer, 0, _Buffer.Length, AddressOf DoReadData, Me)
    End Sub

    Public Sub Close()
        If Client IsNot Nothing Then Client.Close()
        Client = Nothing
        Stream = Nothing
    End Sub

    Private Sub DoReadData(result As IAsyncResult)
        Dim info As Connections = CType(result.AsyncState, Connections)
        Dim message As String = String.Empty
        Dim msgSplit As String = String.Empty
        Dim _sb As New StringBuilder
        Try
            If info.Stream IsNot Nothing AndAlso info.Stream.CanRead Then
                info._LastReadLength = info.Stream.EndRead(result)
                If info._LastReadLength > 0 Then

                    For index As Integer = 0 To _LastReadLength - 1
                        info._DataQueue.Enqueue(info._Buffer(index))
                    Next

                    ' Kumpulkan Bytes Dari Buffer
                    While info._DataQueue.Count > 0
                        _bb.Add(info._DataQueue.Dequeue)
                    End While

                    _sb.Append(System.Text.Encoding.Unicode.GetString(_bb.ToArray))

                    While _sb.ToString.IndexOf(Packet.pEof) > -1
                        If _sb.ToString.Length > _sb.ToString.IndexOf(Packet.pEof) + Packet.pEof.Length Then
                            msgSplit = _sb.ToString.Substring(_sb.ToString.IndexOf(Packet.pEof) + Packet.pEof.Length)
                            _bb.Clear()
                            _bb = System.Text.Encoding.Unicode.GetBytes(msgSplit).ToList
                        Else
                            _bb.Clear()
                        End If
                        'Console.WriteLine(_sb.ToString)
                        RaiseEvent dataResponse(Split(Split(_sb.ToString, Packet.pEof, -1, CompareMethod.Text)(0), Packet.pSplit, -1, CompareMethod.Text))
                        _sb.Clear()
                        _sb.Append(System.Text.Encoding.Unicode.GetString(_bb.ToArray))
                    End While

                    _sb.Clear()
                End If
                If isConnected() Then
                    info.AwaitData()
                Else
                    info._LastReadLength = -1
                End If
            End If

        Catch ex As Exception
            If isConnected() Then
                info.AwaitData()
            Else
                info._LastReadLength = -1
            End If
            Console.WriteLine(ex.Message)
        End Try
    End Sub

    Public Sub sendMessages(ByVal messages As String, ByVal user_id As String)
        If Client IsNot Nothing And Stream IsNot Nothing Then
            Dim messageData() As Byte = System.Text.Encoding.Unicode.GetBytes("100" & Packet.pSplit & user_id & Packet.pSplit & messages & Packet.pEof)
            Stream.Write(messageData, 0, messageData.Length)
            Stream.Flush()
        End If
    End Sub

    Public Sub sendMail(ByVal messages As String, ByVal user_id As String)
        If Client IsNot Nothing And Stream IsNot Nothing Then
            Dim messageData() As Byte = System.Text.Encoding.Unicode.GetBytes("101" & Packet.pSplit & user_id & Packet.pSplit & messages & Packet.pEof)
            Stream.Write(messageData, 0, messageData.Length)
            Stream.Flush()
        End If
    End Sub

    Public Sub Login(ByVal username As String, ByVal password As String)
        If Client IsNot Nothing And Stream IsNot Nothing Then
            Dim messageData() As Byte = System.Text.Encoding.Unicode.GetBytes("1" & Packet.pSplit & username & Packet.pSplit & password & Packet.pSplit & Packet.pEof)
            Stream.Write(messageData, 0, messageData.Length)
            Stream.Flush()
        End If
    End Sub

    Public Sub getUserData()
        If Client IsNot Nothing And Stream IsNot Nothing Then
            Dim messageData() As Byte = System.Text.Encoding.Unicode.GetBytes("10" & Packet.pSplit & "1" & Packet.pEof)
            Stream.Write(messageData, 0, messageData.Length)
            Stream.Flush()
        End If
    End Sub

    Public Sub setUserData(ByVal oldPassword As String, ByVal nPassword As String, ByVal cnPassword As String, ByVal nickName As String)
        Console.WriteLine(nickName)
        If Client IsNot Nothing And Stream IsNot Nothing Then
            Dim messageData() As Byte = System.Text.Encoding.Unicode.GetBytes("10" & Packet.pSplit & "2" & Packet.pSplit & oldPassword & Packet.pSplit & nPassword & Packet.pSplit & cnPassword & Packet.pSplit & nickName & Packet.pEof)
            Stream.Write(messageData, 0, messageData.Length)
            Stream.Flush()
        End If
    End Sub
End Class